using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

namespace TripTracker
{
    class GPSConnection
    {
        public bool connected;
        private SerialPort port;
        private static GPSConnection gpsConnection;
        private GPSDataParser gpsDataParser;
        private FileStream fs;
        private StreamWriter sw;
        private String fileName;
        private int timeElapsed;
        private Queue<String> coordinates;

        private GPSConnection() {
            gpsDataParser = new GPSDataParser();
            connected = false;
            timeElapsed = 1;
            fileName = "tripTrack.txt";
            coordinates = new Queue<string>();
        }

        /// <summary>
        /// Get the single instance of this class
        /// </summary>
        /// <returns>Single instance of GPSConnection</returns>
        public static GPSConnection getGPSConnection() {
            if (gpsConnection == null)
                gpsConnection = new GPSConnection();
            
            return gpsConnection;
        }
        /// <summary>
        /// Connects to the GPS device
        /// </summary>
        public Boolean connect()
        {
            if (File.Exists(fileName))
            {
                DialogResult dialogResult = MessageBox.Show("Would you like to start a new trip?\nPress 'No' to continue the previous tracking", "Trackinig", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                switch (dialogResult)
                {
                    case DialogResult.Yes:
                        //if the file already exists it will be overrided,otherwise
                        //a new one will be created
                        fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
                        if (Settings.getSettings().WebTrackerActivated) {
                            //Start a new thread to delete data on server
                            Thread deleteCoordinatesThread = new Thread(new ThreadStart(deleteCoortinatesOnServer));
                            deleteCoordinatesThread.Start();
                        }
                        break;
                    case DialogResult.No:
                        fs = new FileStream(fileName, FileMode.Append, FileAccess.Write);
                        break;
                    case DialogResult.Cancel:
                        return false;
                }
            }
            else
            {
                fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            }
            sw = new StreamWriter(fs);

            port = new SerialPort();
            port.PortName = Settings.getSettings().GPSPort;
            port.BaudRate = 9600;
            port.Parity = Parity.None;
            port.DataBits = 8;
            port.StopBits = StopBits.One;
            try
            {
                port.Open();
                connected = true;
            }
            catch (Exception e)
            {
                throw e;
            }

            try
            {
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
            
        }

        /// <summary>
        /// Event raised up whenewer new data is recived from the GPS device
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (port.IsOpen)
            {
                Thread.Sleep(1000);
                int bnread = port.BytesToRead;
                char[] a_char = new char[bnread];
                int nread = 0;
                nread = port.Read(a_char, 0, bnread);
                string str = new string(a_char, 0, nread); 
                string coordinate = gpsDataParser.GetCoordinates(str);

                if (!coordinate.Equals(""))
                {
                    coordinate +=  "|" + GSMModemConnector.getLAI() + "|" + GSMModemConnector.getCellID();

                    sw.WriteLine(coordinate);

                    if (Settings.getSettings().WebTrackerActivated)
                    {
                        coordinates.Enqueue(coordinate); //bufferize coordinates in queue

                        if (timeElapsed >= Settings.getSettings().WebTrackerSeconds)
                        {

                            try
                            {
                                //Start a new thread to send data to server
                                Thread sendThread = new Thread(new ThreadStart(sendCoortinatesToServer));
                                sendThread.IsBackground = true;
                                sendThread.Start();
                            }
                            catch (Exception)
                            {
                                MessageBox.Show("Warning error in sending coordinates!");
                            }
                            finally
                            {
                                timeElapsed = 0;
                            }
                        }
                    }
                }

                timeElapsed++;
            }
        }

        /// <summary>
        /// Delete all the user's coordinates on the server
        /// </summary>
        private void deleteCoortinatesOnServer()
        {
            try
            {
                TripTrackerWebService.TripTrackerWebService TripTrackerWebService = new TripTracker.TripTrackerWebService.TripTrackerWebService();
                TripTrackerWebService.deleteUserCoordinates(Settings.getSettings().WebTrackerUserName);
            }
            catch (Exception) //Catch no connection exception
            {
                MessageBox.Show("Cannot delete coordinates on server!");
            }
        }

        /// <summary>
        /// Send user's coordinates to the server
        /// </summary>
        private void sendCoortinatesToServer() {
            try
            {
                String[] myCoordinates = coordinates.ToArray();
                coordinates.Clear();
                TripTrackerWebService.TripTrackerWebService TripTrackerWebService = new TripTracker.TripTrackerWebService.TripTrackerWebService();
                TripTrackerWebService.addCoordinates(Settings.getSettings().WebTrackerUserName, myCoordinates);          
            }
            catch (Exception) //Catch no connection exception
            {
                // no messagebox to prevent battery-discharge
            }
        }

        /// <summary>
        /// Disconnects to the GPS device
        /// </summary>
        public void disconnect()
        {
            if (port.IsOpen)
            {
                port.Close();
                connected = false;
            }
            sw.Close();
            fs.Close();
        }
    }
}
